import matplotlib.pyplot as plt
#%matplotlib notebook
%matplotlib widget
%matplotlib inline
    
import pandas as pd
from mpl_toolkits import mplot3d
#from mpl_toolkits.mplot3d import Axes3D

import numpy as np

deaths = pd.read_excel ("deathsyoauk2017tablesfinal.xls", nrows=106, usecols="B:BD", sheet_name="Table 3", skiprows=[0,1,2])
#deaths = pd.read_excel ("https://bit.ly/2OVxChn", nrows=106, usecols="B:BD", sheet_name="Table 3", skiprows=[0,1,2])
#deaths = pd.read_excel ("https://www.ons.gov.uk/file?uri=/peoplepopulationandcommunity/birthsdeathsandmarriages/deaths/datasets/deathregistrationssummarytablesenglandandwalesdeathsbysingleyearofagetables/2017/deathsyoauk2017tablesfinal.xls", nrows=106, usecols="B:BD", sheet_name="Table 3", skiprows=[0,1,2])

# has suffix in table 1: deaths.rename (columns={"2017p": 2017}, inplace=True) # also need this in read_excel: usecols="B:AS", 

print (deaths.columns, deaths.index)
Index([1963, 1964, 1965, 1966, 1967, 1968, 1969, 1970, 1971, 1972, 1973, 1974,
       1975, 1976, 1977, 1978, 1979, 1980, 1981, 1982, 1983, 1984, 1985, 1986,
       1987, 1988, 1989, 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998,
       1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010,
       2011, 2012, 2013, 2014, 2015, 2016, 2017],
      dtype='int64') RangeIndex(start=0, stop=106, step=1)
print (deaths.shape)
def z_function(x, y):
    return np.sin(np.sqrt(x ** 2 + y ** 2))

def z_f (x, y):
    ret = np.full (shape=(105, 54), fill_value=0.0) #shape = (len(x), len (y)), fill_value = 0.0)
    print ("zf", len (x), len (y), ret.shape)
    for i in range (0, len (x)):
        for j in range (0, 54):
#            print ("setting {}, {} to {}".format (i, j, deaths.iloc[j,i]))
            try:
                #print (deaths.iloc [i, j])
                ret [i, j] = deaths.iloc [i, j] #pass #print (x)
            except Exception as e:
                print ("broken", i, j, ret.shape, deaths.shape, e)
        
    return ret

x= deaths.columns[1:] # columns 0 is the header for Ages
y= deaths.index [1:] # index[0] is the header


X, Y = np.meshgrid(x, y)
Z = z_f (X, Y)
(106, 55)
zf 105 105 (105, 54)

Evolution of Age at Death for England Tells many Stories#

The plot below is intended to be interactive: you can zoom in, out and around it to get a feel for the overall shape and anomalies.

This quite simple presentation of how the age at death has evolved can support a number of interesting stories, including:

Those not born during WWI and WWII#

The grooves of those not born due to soldiers at war, and the corresponding peaks from home comings carve through the ageing peaks

How dangerous the first year of life used to be#

The first year of life is still much more dangerous than the following decades, but it used to be much worse and was until the early ’70s the most dangerous age to be.

The slight uptick of risk for adolescents and early adulthood#

Although middle ages has got considerably safer, life has not extended#

The trailing edge of the curve gets increasingly steep. Unfortunately for many, much of the extension is much more about living with poor health conditions, rather than enjoying later life.

Averages can be misleading#

Taking the early annual snapshots, especially, illustrates how misleading ‘life expectancy’ for a population can be. Although it’s not easy to trace the actual age at death for any give cohort - there aren’t enough years covered to do this - a good approximation can be deduced by slicing along a year. This exercise illustrates how it is possible for the expected life span for a given group to be skewed by infant death in particular, and early deaths in general.

# from plotly example

# Import dependencies
import plotly
import plotly.graph_objs as go

# Configure Plotly to be rendered inline in the notebook.
plotly.offline.init_notebook_mode()

# Configure the trace.
#trace = go.Scatter3d(
#    x= X.flatten(), #[1, 2, 3],  # <-- Put your data instead
#    y= Y.flatten(), #[4, 5, 6],  # <-- Put your data instead
#    z= Z.flatten(), #[7, 8, 9],  # <-- Put your data instead
#    mode='markers',
#    marker={
#        'size': 10,
#        'opacity': 0.8,
#    }
#)

figure = go.Figure (data=[go.Surface (x=X, y=Y, z=Z, opacity=0.5)])

# Configure the layout.
layout = go.Layout(
    margin={'l': 0, 'r': 0, 'b': 0, 't': 0}
)

#data = [trace]

#plot_figure = go.Figure(data=data, layout=layout)

figure.update_layout(
    title=dict(
        text="Evolution of Age at Death"
    ),
    width=1200, height=1000,
    scene = dict (
        xaxis = dict (title= "year"),
        yaxis = dict (title="age"),
        zaxis = dict (title="count")
    ),
    #zaxis = dict (title="z title"),
    legend=dict(
        title=dict(
            text="Legend Title"
        )
    ),
    font=dict(
        family="Courier New, monospace",
        size=18,
        color="RebeccaPurple"
    )
)

#plotly.offline.iplot(plot_figure)
plotly.offline.iplot(figure)